﻿using System;
using System.Linq;
using System.Data;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using EAF.Utility;
using EAF.DBC;
using EAF.DBC.LogHandle;
using EAF.Web;
using App.Utility;
using App.Utility.ComEntity;
using App.Utility.FileHandle;
using App.Model;
using App.Model.Main;
using App.DTO.Main;
using App.IServer.Main;
using App.Server.Main;

namespace App.Admin.Controllers
{
    /// <summary>
    /// 系统登录
    /// </summary>
    public class SysLoginController : ApiController
    {
        private readonly SysUserService sysUserService = null;
        private readonly SysRoleService sysRoleService = null;
        private readonly SysModuleService sysModuleService = null;
        private readonly SysApiService sysApiService = null;
        private readonly SysLoginService sysLoginService = null;
        private readonly SysPlatformService sysPlatformService = null;

        //使用依赖注入获取服务
        public SysLoginController(ISysUserService sysUser, ISysRoleService sysRole, ISysModuleService sysModule, ISysApiService sysApi, ISysLoginService sysLogin, ISysPlatformService sysPlatform)
        {
            sysUserService = sysUser as SysUserService;
            sysRoleService = sysRole as SysRoleService;
            sysModuleService = sysModule as SysModuleService;
            sysApiService = sysApi as SysApiService;
            sysLoginService = sysLogin as SysLoginService;
            sysPlatformService = sysPlatform as SysPlatformService;
        }

        #region 登录相关

        /// <summary>
        /// 系统登录
        /// </summary>
        /// <param name="entity">json对象</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [AdminNoLogin]
        [AdminNoAction]
        [Transactional(typeof(AppMainContext), transDescription: "系统登录")]
        public JsonR Token([FromBody] AdminLoginReq entity)
        {
            var userInfo = sysUserService.Select.DisableGlobalFilter().Where(a => a.Account == entity.account).First();
            if (userInfo == null)
            {
                return RespCode.UL_用户名不存在.JsonR();
            }
            else
            {
                if (!userInfo.Valid || userInfo.Deleted)
                {
                    return RespCode.UL_账户被禁用或已删除.JsonR();
                }
            }

            //对密码操作 
            var pwd = DoEncrypt.MD5(userInfo.Salt + entity.password);
            if (pwd == userInfo.Password)
            {
                AdminLoginSession<SysUser> adminLoginSession = new AdminLoginSession<SysUser>()
                {
                    User = userInfo
                };

                if (entity.platformId == 0)
                {
                    entity.platformId = userInfo.DefPlatform;
                }
                if (entity.platformId == 0)
                {
                    return RespCode.UL_没有登录子系统.JsonR();
                }

                //前端子系统
                List<SysPlatformResp> respPlatform = null;

                if (userInfo.IsAdministrator)
                {
                    //所有子系统
                    respPlatform = sysPlatformService.Select.ToList(o => new SysPlatformResp(o));
                }
                else
                {
                    //处理后台权限模块
                    AdminTokenOperation.RoleHandle(userInfo, sysRoleService.GetCacheList(), adminLoginSession);

                    respPlatform = new List<SysPlatformResp>();
                    for (int i = 0; i < adminLoginSession.LstPlatform.Count; i++)
                    {
                        var sp = sysPlatformService.Detail(adminLoginSession.LstPlatform[i]);
                        respPlatform.Add(new SysPlatformResp(sp));
                    }
                }

                //生成token
                if (AdminTokenOperation.SetTokenSession(AppData.PlatformId, adminLoginSession, sysLoginService))
                {
                    userInfo.LastLoginTime = DateTime.Now;
                    sysUserService.Update(userInfo);
                    var respUser = new SysUserResp(userInfo);
                    var respModule = new List<ModuleAuthResp>();
                    //前端模块处理
                    if (userInfo.IsAdministrator)
                    {
                        AdminTokenOperation.HandleTreeModule(respModule,
                            sysModuleService.GetCacheList().Where(a => a.PlatformId == entity.platformId).OrderBy(a => a.SortNo).ToList(),
                            sysApiService.GetCacheList().Where(a => a.PlatformId == entity.platformId).ToList());
                    }
                    else
                    {
                        var lstSysModule = sysModuleService.GetCacheList().Where(a => a.PlatformId == entity.platformId && adminLoginSession.LstModule.Contains(a.Id)).OrderBy(a => a.SortNo).ToList();
                        var lstSysApi = sysApiService.GetCacheList().Where(a => a.PlatformId == entity.platformId && adminLoginSession.LstApi.Contains(a.Id)).ToList();
                        AdminTokenOperation.HandleTreeModule(respModule, lstSysModule, lstSysApi);
                    }

                    var resp = new AdminLoginResp()
                    {
                        uId = userInfo.Id,
                        token = adminLoginSession.Token,
                        refToken = adminLoginSession.RefToken,
                        adminInfo = respUser,
                        authInfo = respModule,
                        platformInfo = respPlatform,
                        platformId = entity.platformId
                    };

                    return RespCode.OP_操作成功.JsonR(resp);
                }
                else
                {
                    return RespCode.E_程序异常.JsonR("生成设置token失败");
                }
            }
            else
            {
                return RespCode.UL_用户名或者密码错误.JsonR();
            }

        }

        /// <summary>
        /// 系统退出
        /// </summary> 
        /// <returns>操作结果</returns>
        [HttpGet]
        [AdminNoAction]
        [Transactional(typeof(AppMainContext), transDescription: "系统退出")]
        public JsonR SignOut()
        {
            var session = AdminTokenOperation.GetTokenSession(HttpContext);
            if (session == null)
            {
                return RespCode.UL_用户名不存在.JsonR();
            }
            else
            {
                //清除缓存token
                //var loginSession = AdminTokenOperation.GetTokenSession(HttpContext);
                if (AdminTokenOperation.ClearTokenSession(AppData.PlatformId, sysLoginService))
                {
                    //RecordBehavior(new RLogBehavior
                    //{
                    //    Level = LogLevel.Info,
                    //    Table = "SysUser",
                    //    Method = EntityMethod.M_查看,
                    //    Content = $"账号：{loginSession.User.Account} token：{loginSession.Token} refToken：{loginSession.RefToken}",
                    //    Description = "系统注销"
                    //});
                    return RespCode.OP_操作成功.JsonR();
                }
                else
                {
                    return RespCode.OP_操作失败.JsonR("清除缓存token失败请重试！");
                }
            }
        }

        /// <summary>
        /// 获取登录用户授权
        /// </summary> 
        /// <param name="pId">子系统id</param>
        /// <returns>操作结果</returns>
        [HttpGet]
        [AdminNoAction]
        public JsonR GetAuth(int pId = 1)
        {
            var session = AdminTokenOperation.GetTokenSession(HttpContext);
            if (session == null)
            {
                return RespCode.UL_会话超时.JsonR();
            }
            else
            {
                var userInfo = session.User;
                var respModule = new List<ModuleAuthResp>();
                //前端模块处理
                if (userInfo.IsAdministrator)
                {
                    AdminTokenOperation.HandleTreeModule(respModule,
                        sysModuleService.GetCacheList().Where(a => a.PlatformId == pId).OrderBy(a => a.SortNo).ToList(),
                        sysApiService.GetCacheList().Where(a => a.PlatformId == pId).ToList());
                }
                else
                {
                    var lstSysModule = sysModuleService.GetCacheList().Where(a => a.PlatformId == pId && session.LstModule.Contains(a.Id)).OrderBy(a => a.SortNo).ToList();
                    var lstSysApi = sysApiService.GetCacheList().Where(a => a.PlatformId == pId && session.LstApi.Contains(a.Id)).ToList();
                    AdminTokenOperation.HandleTreeModule(respModule, lstSysModule, lstSysApi);
                }
                var resp = new AdminLoginResp()
                {
                    authInfo = respModule
                };
                return RespCode.OP_操作成功.JsonR(resp);
            }

        }

        /// <summary>
        /// 获取登录用户所有平台授权
        /// </summary>
        /// <returns>操作结果</returns>
        [HttpGet]
        [AdminNoAction]
        public JsonR GetAllAuth()
        {
            var session = AdminTokenOperation.GetTokenSession(HttpContext);
            if (session == null)
            {
                return RespCode.UL_会话超时.JsonR();
            }
            else
            {
                var userInfo = session.User;
                var respModule = new List<ModuleAuthResp>();
                //前端模块处理
                if (userInfo.IsAdministrator)
                {
                    var allPlatform = sysPlatformService.GetCacheList();

                    //将平台作为根节点
                    for (int i = 0; i < allPlatform.Count; i++)
                    {
                        var p = allPlatform[i];
                        var crm = new List<ModuleAuthResp>();

                        AdminTokenOperation.HandleTreeModule(crm,
                            sysModuleService.GetCacheList().Where(a => a.PlatformId == p.Id).OrderBy(a => a.SortNo).ToList(),
                            sysApiService.GetCacheList().Where(a => a.PlatformId == p.Id).ToList());

                        var m = new ModuleAuthResp
                        {
                            childs = crm,
                            entity = new ModuleAuthResp.ModuleAuthItem
                            {
                                icon = p.Icon,
                                index = p.RouterPath,
                                name = p.Name,
                                auth = new List<string>()
                            }
                        };
                        respModule.Add(m);
                    }
                }
                else
                {
                    //当前用户拥有的api和模块
                    var lstSysModule = sysModuleService.GetCacheList().Where(a => session.LstModule.Contains(a.Id)).OrderBy(a => a.SortNo).ToList();
                    var lstSysApi = sysApiService.GetCacheList().Where(a => session.LstApi.Contains(a.Id)).ToList();

                    //根据平台过滤
                    var allPlatform = sysPlatformService.GetCacheList().Where(a => session.LstPlatform.Contains(a.Id)).ToList();
                    for (int i = 0; i < allPlatform.Count; i++)
                    {
                        var p = allPlatform[i];
                        var crm = new List<ModuleAuthResp>();

                        AdminTokenOperation.HandleTreeModule(crm,
                            lstSysModule.Where(a => a.PlatformId == p.Id).OrderBy(a => a.SortNo).ToList(),
                            lstSysApi.Where(a => a.PlatformId == p.Id).ToList());

                        var m = new ModuleAuthResp
                        {
                            childs = crm,
                            entity = new ModuleAuthResp.ModuleAuthItem
                            {
                                icon = p.Icon,
                                index = p.RouterPath,
                                name = p.Name,
                                auth = new List<string>()
                            }
                        };
                        respModule.Add(m);
                    }
                }
                return RespCode.OP_操作成功.JsonR(respModule);
            }

        }

        /// <summary>
        /// 获取登录用户信息
        /// </summary> 
        /// <returns>操作结果</returns>
        [HttpGet]
        [AdminNoAction]
        public JsonR GetUserInfo()
        {
            var session = AdminTokenOperation.GetTokenSession(HttpContext);
            if (session == null)
            {
                return RespCode.UL_用户名不存在.JsonR();
            }
            else
            {
                return RespCode.OP_操作成功.JsonR(session.User);
            }

        }

        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="entity">json对象</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [AdminNoLogin]
        [AdminNoAction]
        [Transactional(typeof(AppMainContext), transDescription: "刷新token")]
        public JsonR RefreshToken([FromBody] RefreshTokenReq entity)
        {
            SysUser userInfo;
            SysLogin sysLogin;
            if (entity.uId == 0)
            {
                var tArr = entity.refToken.Split("_", StringSplitOptions.RemoveEmptyEntries);
                int uId = tArr[0].Replace("@", "").ToInt();
                userInfo = sysUserService.Detail(uId);
            }
            else
            {
                userInfo = sysUserService.Detail(entity.uId);
            }
            if (userInfo == null)
            {
                return RespCode.UL_用户名不存在.JsonR();
            }

            sysLogin = sysLoginService.Select.Where(w => w.UserId == userInfo.Id && w.PlatformId == AppData.PlatformId).First();
            //sysLoginService.List8Lambda(w => w.UserId == userInfo.Id && w.PlatformId == pId);
            if (sysLogin == null)
            {
                return RespCode.UL_用户名不存在.JsonR("未找到上次登录信息");
            }
            if (sysLogin.RefToken != entity.refToken)
            {
                return RespCode.UL_RefreshToken失效.JsonR();
            }

            //创建新的登录会话
            AdminLoginSession<SysUser> adminLoginSession = new AdminLoginSession<SysUser>()
            {
                User = userInfo
            };
            if (userInfo.IsAdministrator)
            {

            }
            else
            {
                //处理后台权限模块
                AdminTokenOperation.RoleHandle(userInfo, sysRoleService.GetCacheList(), adminLoginSession);
            }

            //生成token
            if (AdminTokenOperation.SetTokenSession(AppData.PlatformId, adminLoginSession, sysLoginService, entity.token))
            {
                userInfo.LastLoginTime = DateTime.Now;
                sysUserService.Update(userInfo);
                var resp = new AdminLoginResp()
                {
                    uId = entity.uId,
                    token = adminLoginSession.Token,
                    refToken = adminLoginSession.RefToken
                };
                return RespCode.OP_操作成功.JsonR(resp);
            }
            else
            {
                return RespCode.E_程序异常.JsonR("生成设置token失败");
            }
        }

        #endregion

        #region 增删改查列表分页等基础操作

        /// <summary>
        /// 分页列表
        /// </summary>
        /// <param name="model">查询参数</param>
        /// <returns>分页数据</returns>
        [HttpGet]
        public JsonR<JsonPage<SysLoginResp>> PageList([FromQuery] SysLoginPageReq model)
        {
            var query = model.Query(sysLoginService.DBC);

            JsonPage<SysLoginResp> pageList = new JsonPage<SysLoginResp>();
            pageList.total = query.Count().ToInt();
            pageList.pageSize = model.pageSize;
            pageList.pageIndex = model.pageIndex;
            pageList.list = query.Page(model.pageIndex, model.pageSize).ToList(o => new SysLoginResp(o));

            var resp = RespCode.OP_操作成功.JsonRT(pageList);
            //resp.AddEnumKeyValueList(typeof(RespCode));
            return resp;
        }

        /// <summary>
        /// 导出excel
        /// </summary>
        /// <param name="model">查询参数</param>
        /// <param name="fields">需要导出的字段 如：id|</param>
        /// <param name="token">登录用户令牌</param>
        /// <param name="uId">登录用户Id</param>
        /// <param name="frontUrl">前端页面域名 末尾不要带/</param>
        /// <returns>excel文件流</returns>
        [HttpGet]
        [Produces("multipart/form-data")]
        [AdminNoLogin]
        [AdminNoAction]
        [AdminNoApiLog]
        public IActionResult ExportExcel([FromQuery] SysLoginPageReq model, string fields = null, string token = "", int uId = 0, string frontUrl = "")
        {
            //验证权限 此接口可通过url直接访问
            var splitPath = Request.Path.ToString().Split('/', StringSplitOptions.RemoveEmptyEntries);
            var vr = AdminTokenOperation.VerifyToken(HttpContext, token, splitPath[1], splitPath[2], 0, uId);
            if (vr.code != RespCode.OP_操作成功.GetHashCode())
            {
                return Redirect(frontUrl + vr.body);
            }

            //查询数据
            var sql = model.Query(sysLoginService.DBC).ToSql();
            var dataTable = sysLoginService.DBC.SqlExecuteDataTable(sql);
            var tableInfo = sysLoginService.DBC.Orm.CodeFirst.GetTableByEntity(typeof(SysLogin));

            //调整数据 移除无用列
            dataTable.Columns.Remove(tableInfo.ColumnsByCs[nameof(SysLogin.Version)].Attribute.Name);
            dataTable.Columns.Remove(tableInfo.ColumnsByCs[nameof(SysLogin.Deleted)].Attribute.Name);
            dataTable.Columns.Remove(tableInfo.ColumnsByCs[nameof(SysLogin.DeleteTime)].Attribute.Name);

            //修改列名为字段注释
            dataTable.DataTableExportHandle<SysLogin>(tableInfo, fields);

            RecordBehavior(new RLogBehavior
            {
                Table = nameof(SysLogin),
                Method = EntityMethod.M_查看,
                Content = $"成功导出了ID为：{dataTable.GetColumnLong(tableInfo.ColumnsByCs[nameof(PrimaryKeyColumn<int>.Id)].Comment).ToJson()}的记录",
                Description = "导出excel"
            });

            //转换excel文件流 
            var fileName = (tableInfo.Comment.IsNull() ? nameof(SysLogin) : tableInfo.Comment) + DateTime.Now.Format_yyyyMMddHHmmss(false) + ".xlsx";
            var byteFile = DoExcel.DataTableToExcelByte(dataTable, "sheet1", true, fileName);
            return File(byteFile, "application/octet-stream", fileName);
        }

        /// <summary>
        /// 导入excel
        /// </summary>
        /// <param name="file1">文件</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [Consumes("multipart/form-data")]
        [Transactional(typeof(AppMainContext), IsolationLevel.Serializable, "导入excel")]
        public JsonR ImportExcel(IFormFile file1 = null)
        {
            if (Request.Form.Files.Count == 0)
            {
                return RespCode.OP_参数异常.JsonR("请至少上传一个文件！");
            }

            var checkResult = file1.Admittance();
            if (checkResult.JsonResult.code == 0)
            {
                if (checkResult.FileType == "excel")
                {
                    //读取excel
                    var dataTable = DoExcel.ExcelStreamToDataTable(file1.OpenReadStream(), file1.FileName);
                    //列名转换为db实体类对应的字段名
                    var tableConfig = sysLoginService.DBC.Orm.CodeFirst.GetTableByEntity(typeof(SysLogin));
                    dataTable.DataTableImportHandle<SysLogin>(tableConfig);
                    //转换为db实体集合
                    var lstDbEntity = new List<SysLogin>();
                    var dicError = new Dictionary<int, Dictionary<string, List<string>>>();
                    var dicProp = typeof(SysLogin).GetProperties().ToDictionary(k => k.Name);
                    for (int i = 0; i < dataTable.Rows.Count; i++)
                    {
                        var row = dataTable.Rows[i];
                        var dbEntity = row.ToObject<SysLogin>(dataTable.Columns, i, dicError, dicProp, tableConfig);
                        dbEntity.InitializeGeneralField(HttpContext);
                        lstDbEntity.Add(dbEntity);
                        //对每行数据业务验证 有问题请添加验证失败消息 dicError.AddImportVerifyError(i+2, "excel列名", "消息"); 不可移除集合数据 否则下方验证的行号可能无法对应

                    }

                    var insertIdentity = dataTable.Columns.Contains(nameof(SysLogin.Id));
                    //通用检查实体类标记了[ImportRepeatVerify]的字段有没有重复值
                    var lstVerifyExcelRepeat = sysLoginService.DBC.VerifyImportRepeatColumn(lstDbEntity, dicError, tableConfig, insertIdentity, dicProp);
                    //通用检查实体类标记了[ImportRelationIdVerify(typeof(SysParam), nameof(SysParam.Name))]的字段外键关联记录是否存在
                    var dicVerifyExcelRelationId = sysLoginService.DBC.VerifyImportRelationIdColumn(lstDbEntity, dicError, tableConfig, dicProp);
                    //处理验证结果
                    var lstError = dicError.ToList();
                    var resp = new JsonImportError { errorTotal = lstError.Count, simpleMessage = lstError };
                    if (lstError.Count > 0)
                    {
                        return RespCode.OP_操作失败.JsonR(resp, $"数据验证失败有{resp.errorTotal}条不合法记录！");
                    }
                    //导入表 包含id则自动插入
                    int rowCount = sysLoginService.Add(lstDbEntity, insertIdentity);
                    return RespCode.OP_操作成功.JsonR($"成功导入{rowCount}条记录！");

                }
                else
                {
                    return RespCode.OP_操作失败.JsonR("上传的类型不支持，请上传excel文件！");
                }
            }
            else
            {
                return checkResult.JsonResult;
            }

        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity">json对象</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [Transactional(typeof(AppMainContext))]
        public JsonR Add([FromBody] SysLoginReq entity)
        {
            var dbEntity = entity.ConvertDbEntity(new SysLogin());
            dbEntity.InitializeGeneralField(HttpContext);

            var result = sysLoginService.Add(dbEntity);
            if (result > 0)
            {
                return RespCode.OP_操作成功.JsonR(new { insId = result });
            }
            else
            {
                return RespCode.OP_操作失败.JsonR();
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity">json对象</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [Transactional(typeof(AppMainContext))]
        public JsonR Delete([FromBody] Json_ReqIds<int> entity)
        {
            if (entity == null || entity.ids == null)
            {
                return RespCode.OP_参数异常.JsonR();
            }

            int count = sysLoginService.Delete(entity.ids);
            return RespCode.OP_操作成功.JsonR(new { delCount = count });
        }

        /// <summary>
        /// 销毁
        /// </summary>
        /// <param name="entity">json对象</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [Transactional(typeof(AppMainContext))]
        public JsonR Destory([FromBody] Json_ReqIds<int> entity)
        {
            if (entity == null || entity.ids == null)
            {
                return RespCode.OP_参数异常.JsonR();
            }

            int count = sysLoginService.Delete(entity.ids, 1);

            return RespCode.OP_操作成功.JsonR(new { delCount = count });
        }

        /// <summary>
        /// 还原
        /// </summary>
        /// <param name="entity">json对象</param> 
        /// <returns>操作结果</returns>
        [HttpPost]
        [Transactional(typeof(AppMainContext))]
        public JsonR Restore([FromBody] Json_ReqIds<int> entity)
        {
            if (entity == null || entity.ids == null)
            {
                return RespCode.OP_参数异常.JsonR();
            }

            int count = sysLoginService.DBC.Update<SysLogin>()
                .DisableGlobalFilter()
                .Set(f => f.Deleted, false)
                .Where(w => w.Deleted == true && entity.ids.Contains(w.Id)).ExecuteAffrows();

            if (count > 0)
            {
                RecordBehavior(new RLogBehavior
                {
                    Table = nameof(SysLogin),
                    Method = EntityMethod.M_还原,
                    Content = $"还原了{count}条记录，ID为：{entity.ids.ToJson()}",
                    Description = "CRUD操作"
                });
            }

            return RespCode.OP_操作成功.JsonR(new { resCount = count });
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="entity">json对象</param>
        /// <returns>操作结果</returns>
        [HttpPost]
        [Transactional(typeof(AppMainContext))]
        public JsonR Modify([FromBody] SysLoginReq entity)
        {
            var dbOldEntity = sysLoginService.Detail(entity.id);
            if (dbOldEntity == null)
            {
                return RespCode.OP_未找到对象.JsonR();
            }
            else
            {
                var dbNewEntity = dbOldEntity.AutoMapObjectTo(new SysLogin());
                dbNewEntity = entity.ConvertDbEntity(dbNewEntity);
                var result = sysLoginService.Update(dbNewEntity, dbOldEntity);
                if (result > 0)
                {
                    return RespCode.OP_操作成功.JsonR();
                }
                else
                {
                    return RespCode.OP_操作失败.JsonR();
                }
            }
        }

        /// <summary>
        /// 详情
        /// </summary>
        ///  <param name="id">唯一标示</param>
        /// <returns>操作结果</returns>
        [HttpGet]
        public JsonR<SysLoginResp> Detail(int id)
        {
            var dbEntity = sysLoginService.Detail(id, true);
            if (dbEntity == null)
            {
                return RespCode.OP_未找到对象.JsonRT<SysLoginResp>();
            }

            var result = new SysLoginResp(dbEntity);

            var resp = RespCode.OP_操作成功.JsonRT(result);
            //添加用到键值对
            //resp.AddEnumKeyValueList(typeof(RespCode));
            return resp;
        }

        #endregion

    }
}



